home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: delta / whiteline CD Series - delta.iso / progtool / modula2 / module / easywind.mod < prev    next >
Text File  |  1995-11-25  |  27KB  |  860 lines

  1. IMPLEMENTATION MODULE EasyWindow;
  2.  
  3. FROM SYSTEM IMPORT TSIZE, VAL,ADDRESS,SHIFT,SHORT,ADR,BYTE;
  4.  
  5. FROM Storage IMPORT ALLOCATE,DEALLOCATE;
  6.  
  7. FROM GEMVDIbase IMPORT PxyArrayType, BigPxyArrayType, TextAttrArrayType;
  8.  
  9. FROM VDIRasters IMPORT CopyRasterOpaque,MFDBType,MFDBptr;
  10.  
  11. FROM VDIControls IMPORT SetClipping;
  12.  
  13. FROM VDIAttribs  IMPORT SetFillStyle,SetFillColour,SetFillInteriorStyle,
  14.                         SetGraphicTextColour,SetGraphicTextEffects;
  15.  
  16. FROM VDIInquires IMPORT InquireFillAttributes,InquireTextAttributes;
  17.  
  18. FROM VDIOutputs IMPORT DrawBar,GraphicText;
  19.  
  20. FROM GEMAESbase IMPORT WindowRedraw, WindowTopped, WindowClosed, WindowFulled,
  21.                        WindowArrowed, WindowHorizSlided, WindowVertSlided,
  22.                        WindowSized, WindowMoved, WindowNewTop, WindowKind,
  23.                        WindowName, WindowInfo, WorkXYWH, CurrXYWH, PrevXYWH,
  24.                        FullXYWH, WindowHorizSlide, WindowVertSlide, Top,
  25.                        FirstXYWH, NextXYWH, HorizSliderSize, VertSliderSize,
  26.                        WindowScreen,White,Black,EndUpdate,BeginUpdate,WCWork,
  27.                        WCBorder;
  28.  
  29. FROM AES        IMPORT GrafMouse,FormDialogue,WindowFind,WindowGet,WindowDelete,
  30.                        WindowClose,WindowSet,WindowUpdate,WindowCalc,WindowOpen,
  31.                        GrafGrowBox,GrafShrinkBox,GrafHandle,WindowCreate,FormAlert;
  32.  
  33.  
  34. VAR
  35.     WC,HC,WB,HB : INTEGER;
  36.     handle      : INTEGER;
  37.     Nil2Max     : INTEGER;
  38.  
  39.  
  40. PROCEDURE TerminateWindows;
  41. VAR w: INTEGER;
  42. BEGIN
  43.    FOR w := 1 TO maxwindow DO
  44.        IF windowlist[w] # NIL THEN
  45.           IF windowlist[w]^.opened THEN
  46.               WindowClose(w);
  47.           END(*IF*);
  48.           DEALLOCATE(windowlist[w]);
  49.           WindowDelete(w);
  50.        END(*IF*);
  51.    END(*FOR*);
  52.    w:=SetGraphicTextColour(handle,Black);
  53.    w:=SetGraphicTextEffects(handle,VAL(INTEGER,NoEffects));
  54.  
  55. END TerminateWindows;
  56.  
  57.  
  58. PROCEDURE createWindow (VAR u:        window;
  59.                           x, y, w, h: INTEGER;
  60.                           parts:      WindowElements;
  61.                           title:      ARRAY OF CHAR;
  62.                           textwindow: BOOLEAN;
  63.                           rdp:        RedrawProcType);
  64. VAR  win :windowtype;
  65.      i,wx,wy,ww,wh: INTEGER;
  66.      t :  wstring;
  67.  
  68.  
  69. BEGIN
  70.    IF HIGH(title)>78 THEN
  71.       FOR i:= 0 TO 78 DO
  72.             t[i]:=title[i]
  73.       END(*FOR*);
  74.       t[79]:=0C
  75.    ELSE
  76.       FOR i:= 0 TO HIGH(title) DO
  77.            t[i]:=title[i]
  78.       END(*FOR*);
  79.       t[HIGH(title)+1]:=0C
  80.    END(*IF*);
  81.    IF (w=0) OR (h=0) THEN
  82.       WindowGet(0,WorkXYWH,wx,wy,ww,wh);
  83.       u:=WindowCreate(VAL(INTEGER,parts),wx,wy,ww,wh);
  84.       WindowCalc(WCWork,VAL(INTEGER,parts),wx,wy,ww,wh,x,y,w,h);
  85.       WindowCalc(WCBorder,VAL(INTEGER,parts),x,y,w,h,wx,wy,ww,wh);
  86.    ELSE
  87.       WindowCalc(WCBorder,VAL(INTEGER,parts),x,y,w,h,wx,wy,ww,wh);
  88.       u:=WindowCreate(VAL(INTEGER,parts),wx,wy,ww,wh);
  89.    END(*IF*);
  90.    IF (u>0) AND (u<maxwindow) THEN
  91.          win.handle:=u;
  92.          win.max.x:=wx;
  93.          win.max.y:=wy;
  94.          win.max.w:=ww;
  95.          win.max.h:=wh;
  96.          win.work.x:=x;
  97.          win.work.y:=y;
  98.          win.work.w:=w;
  99.          win.work.h:=h;
  100.          win.total.x:=wx;
  101.          win.total.y:=wy;
  102.          win.total.w:=ww;
  103.          win.total.h:=wh;
  104.          win.min.x:=wx;
  105.          win.min.y:=wy;
  106.          win.min.w:=10*WC;
  107.          win.min.h:=6*HC;
  108.          win.elements:=parts;
  109.          win.fulled:=FALSE;
  110.          win.opened:=FALSE;
  111.          win.ontop:=FALSE;
  112.          win.text:=textwindow;
  113.          win.grow:=growbox;
  114.          win.snap:=Snap;
  115.          IF textwindow THEN
  116.                win.allignX:=WC;
  117.                win.allignY:=HC;
  118.                win.scrollX:=WC;
  119.                win.scrollY:=HC;
  120.          ELSE
  121.                win.allignX:=AllignX;
  122.                win.allignY:=AllignY;
  123.                win.scrollX:=WC;
  124.                win.scrollY:=HC;
  125.          END(*IF*);
  126.          win.row:=1;win.col:=1;
  127.          win.maxrow:=1;
  128.          win.maxcol:=1;
  129.          win.colour:=White;
  130.          win.InteriorStyle:=1C;
  131.          win.FillStyle:=1C;
  132.          win.textcolour:=Black;
  133.          win.texteffects:=NoEffects;
  134.          win.redrawproc:=rdp;
  135.          win.title:=t;
  136.          win.info:=0C;
  137.          win.reference:=NIL;
  138.          ALLOCATE(windowlist[u],TSIZE(windowtype));
  139.          windowlist[u]^:=win;
  140.          SetTitle(u,title);
  141.    ELSE
  142.          t:="[3][Zu viele Fenster offen][Abbruch]";
  143.          x:=FormAlert(1,t);
  144.    END(*IF*);
  145. END  createWindow;
  146.  
  147.   (* Erzeugt die im AES und in diesem Modul notwendigen Datenstrukturen
  148.      zur Verwaltung eines Fensters, das jedoch noch nicht gezeichnet
  149.      wird.
  150.  
  151.      x, y, w und h beschreiben die maximale Grösse des äusseren Fenster-
  152.      randes. Sind w oder h gleich 0, so wird die Grösse des Desktops
  153.      ohne Menüleiste übernommen.
  154.  
  155.      "parts" ist ein Set aus den gewünschten Fensterelementen.
  156.  
  157.      "title" ist der Fenstertitel.
  158.  
  159.      "textwindow" soll bei Textfenstern auf TRUE gesetzt werden,
  160.      der Fensterursprung wird dann an das Textraster angepaßt.
  161.  
  162.      "rdp" ist die Redraw-Prozedur, also die Prozedur, die den Inhalt
  163.      des Fensters zeichnet. Sie wird beim Aufruf der Prozedur "DoRedraw"
  164.      (siehe unten) so oft aufgerufen wird, bis die Rechteckliste, die
  165.      die sichtbaren Teile des Fensters angibt, abgearbeitet worden ist.
  166.      An "rdp" wird beim Aufruf ein Rechteck übergeben, das die neu
  167.      zu zeichnende Fläche angibt. Wurde beim Aufruf von "DoRedraw"
  168.      der Paramter "clip" auf FALSE gesetzt, muss "rdp" alle Ausgaben
  169.      selbst auf diese Fläche begrenzen, was die Ausgabe vor allem bei
  170.      Text stark beschleunigen kann, aber bei teilweise verdeckten Fen-
  171.      stern kaum durchführbar ist. Beim Zeichnen von Objektbäumen wird
  172.      das Begrenzungsrechteck direkt beim "ObjectDraw"-Aufruf angegeben.
  173.   *)
  174.  
  175.  
  176. PROCEDURE clearWindow  (u: window );
  177. VAR win : windowtype;
  178.     rect :rectangle;
  179. BEGIN
  180.   IF  windowlist[u] # NIL THEN
  181.     win:=windowlist[u]^;
  182.     IF win.opened THEN
  183.        WindowGet(u,WorkXYWH,rect.x,rect.y,rect.w,rect.h);
  184.        rect.x:=0;rect.y:=0;
  185.        clearrect(u,rect);
  186.     END(*IF*);
  187.  END(*IF*);
  188. END  clearWindow;
  189.  
  190. PROCEDURE clearrect (u: window ; rect: rectangle);
  191. VAR  win : windowtype;
  192.      pxy : PxyArrayType;
  193.     Bpxy  :BigPxyArrayType;
  194.      c,s,x,y,w,h:INTEGER;
  195. BEGIN
  196.   IF  windowlist[u] # NIL THEN
  197.     win:=windowlist[u]^;
  198.     IF win.opened THEN
  199.        WindowGet(u,WorkXYWH,x,y,w,h);
  200.        rect.x:=rect.x+x;
  201.        rect.y:=rect.y+y;
  202.        RectToPxy(rect,pxy);
  203.        (* Derzeitige Füllatribute und Farben erfragen *)
  204.        InquireFillAttributes(handle,Bpxy);
  205.        MouseOff;
  206.        c:=SetFillColour(handle,win.colour);
  207.        s:=SetFillStyle (handle,VAL(INTEGER,win.FillStyle));
  208.        s:=SetFillInteriorStyle (handle,VAL(INTEGER,win.InteriorStyle));
  209.        DrawBar(handle,pxy);
  210.        (* Füll-Atribute u. -Farbe wierherstellen *)
  211.        c:=SetFillColour(handle,Bpxy[1]);
  212.        s:=SetFillStyle (handle,Bpxy[2]);
  213.        s:=SetFillInteriorStyle (handle,Bpxy[0]);
  214.        MouseOn;
  215.     END(*IF*);
  216.  END(*IF*);
  217. END  clearrect;
  218.  
  219.   (* Löscht einen Rechteckbereich innerhalb des Fensters "u" in
  220.      Fensterkoordinaten *)
  221.  
  222. PROCEDURE closeWindow  (u: window );
  223. VAR win : windowtype;
  224.     x,y,w,h :INTEGER;
  225.  
  226. BEGIN
  227.   IF  windowlist[u] # NIL THEN
  228.     win:=windowlist[u]^;
  229.  
  230.     IF win.opened THEN
  231.           WindowGet(u,CurrXYWH,x,y,w,h);
  232.           IF win.grow THEN
  233.              GrafShrinkBox(x,y,WC,HC,x,y,w,h)
  234.           END(*IF*);
  235.           WindowClose(u);
  236.     END(*IF*);
  237.     win.opened:=FALSE;
  238.     win.ontop:=FALSE;
  239.     windowlist[u]^:=win;
  240.   END(*IF*);
  241. END  closeWindow;
  242.  
  243. PROCEDURE deleteWindow (VAR u: window );
  244. VAR win : windowtype;
  245. BEGIN
  246.   IF  windowlist[u] # NIL THEN
  247.     win:=windowlist[u]^;
  248.     IF win.opened THEN
  249.           WindowClose(u);
  250.     END(*IF*);
  251.     WindowDelete(u);
  252.     DEALLOCATE(windowlist[u]);
  253.     windowlist[u]:= NIL;
  254.     u:=-1
  255.   END(*IF*);
  256. END  deleteWindow ;
  257.  
  258. PROCEDURE fullWindow   (u: window );
  259. VAR win : windowtype;
  260.     x,y,w,h :INTEGER;
  261. BEGIN
  262.   IF  windowlist[u] # NIL THEN
  263.     win:=windowlist[u]^;
  264.     IF ~win.fulled THEN
  265.           IF win.grow THEN
  266.               WindowGet(u,CurrXYWH,x,y,w,h);
  267.               GrafGrowBox(x,y,w,h, win.max.x,win.max.y,win.max.w,win.max.h);
  268.           END(*IF*);
  269.           WindowSet(u,CurrXYWH,win.max.x,win.max.y,win.max.w,win.max.h);
  270.           win.fulled := TRUE
  271.     ELSE
  272.           WindowGet(u,PrevXYWH,x,y,w,h);
  273.           IF  (x=win.max.x) AND  (y=win.max.y) AND
  274.               (w=win.max.w) AND  (h=win.max.h) THEN
  275.                  x:=win.min.x;
  276.                  y:=win.min.y;
  277.                  w:=win.min.w;
  278.                  h:=win.min.h;
  279.           END(*IF*);
  280.           IF win.grow THEN
  281.               GrafShrinkBox(x,y,w,h, win.max.x,win.max.y,win.max.w,win.max.h);
  282.           END(*IF*);
  283.           WindowSet(u,CurrXYWH,x,y,w,h);
  284.           win.fulled := FALSE
  285.     END(*IF*);
  286.     win.opened:=TRUE;
  287.     WindowGet(u,CurrXYWH,x,y,w,h);
  288.     win.total.x:=x;
  289.     win.total.y:=y;
  290.     win.total.w:=w;
  291.     win.total.h:=h;
  292.     WindowGet(u,WorkXYWH,x,y,w,h);
  293.     win.work.x :=x;
  294.     win.work.y :=y;
  295.     win.work.w :=w;
  296.     win.work.h :=h;
  297.     windowlist[u]^:=win;
  298.   END(*IF*);
  299. END  fullWindow;
  300.  
  301. PROCEDURE SnapWindow(u:window;VAR x,y,w,h:INTEGER);
  302.                                  (* Verkleinert das Fenster bei Verschiebungen so
  303.                                    das es vollständig auf dem Desktop zu sehen ist*)
  304. VAR win:windowtype;
  305.     x0,y0,w0,h0 :INTEGER;
  306. BEGIN
  307.   IF  windowlist[u] # NIL THEN
  308.     win:=windowlist[u]^;
  309.       WindowGet(0,WorkXYWH,x0,y0,w0,h0);
  310.       IF (x+win.min.w)>(w0) THEN
  311.           x:=x0+w0-win.min.w
  312.       END(*IF*);
  313.       IF (y+win.min.h)>(h0) THEN
  314.           y:=y0+h0-win.min.h
  315.       END(*IF*);
  316.       IF (x+w) > (x0+w0) THEN
  317.           w:=x0+w0-x;
  318.       END(*IF*);
  319.       IF (y+h) > (y0+h0) THEN
  320.           h:=y0+h0-y;
  321.       END(*IF*);
  322.   END(*IF*);
  323. END  SnapWindow;
  324.  
  325. PROCEDURE AlignWindow(u:window;VAR x,y,w,h:INTEGER);
  326.                                  (* Passt das Fenster bei Verschiebungen an den
  327.                                   Snap-Wert an *)
  328. VAR win : windowtype;
  329. BEGIN
  330.   IF  windowlist[u] # NIL THEN
  331.     win:=windowlist[u]^;
  332.       x:=x+SHIFT(win.allignX,-1)+1;
  333.       x:= win.allignX*(x DIV win.allignX);
  334.       y:=y+SHIFT(win.allignY,-1)+1;
  335.       y:= win.allignY*(y DIV win.allignY)
  336.   END(*IF*);
  337. END  AlignWindow;
  338.  
  339.  
  340. PROCEDURE openWindow   (u: window ; x, y, w, h: INTEGER);
  341. VAR win:windowtype;
  342. BEGIN
  343.   IF  windowlist[u] # NIL THEN
  344.     win:=windowlist[u]^;
  345.     IF (w=0) OR (h=0) THEN
  346.        IF win.grow THEN
  347.               GrafGrowBox(x,y,w,h, win.total.x,win.total.y,win.total.w,win.total.h);
  348.        END(*IF*);
  349.        WindowOpen(u,win.total.x,win.total.y,win.total.w,win.total.h);
  350.     ELSE
  351.        IF win.grow THEN
  352.               GrafGrowBox(x+(w DIV  2),y+(h DIV 2),WC,HC,x,y,w,h)
  353.        END(*IF*);
  354.        WindowOpen(u,x,y,w,h);
  355.     END(*IF*);
  356.     WindowGet(u,CurrXYWH,x,y,w,h);
  357.     win.total.x:=x;
  358.     win.total.y:=y;
  359.     win.total.w:=w;
  360.     win.total.h:=h;
  361.     win.opened:=TRUE;
  362.     WindowGet(u,WorkXYWH,x,y,w,h);
  363.     win.work.x :=x;
  364.     win.work.y :=y;
  365.     win.work.w :=w;
  366.     win.work.h :=h;
  367.     windowlist[u]^:=win;
  368.     WindowGet(u,Top,u,y,w,h);
  369.     topWindow(u);
  370.   END(*IF*);
  371. END  openWindow;
  372.  
  373. PROCEDURE setWindow    (u:window ; x, y, w, h: INTEGER);
  374. VAR win : windowtype;
  375. BEGIN
  376.   IF  windowlist[u] # NIL THEN
  377.     win:=windowlist[u]^;
  378.     IF (win.allignX#1) OR (win.allignY#1) THEN
  379.         AlignWindow(u,x,y,w,h)
  380.     END(*IF*);
  381.     IF win.snap THEN SnapWindow(u,x,y,w,h) END(*IF*);
  382.     IF win.min.w>w THEN w:=win.min.w END(*IF*);
  383.     IF win.min.h>h THEN h:=win.min.h END(*IF*);
  384.     WindowSet(u,CurrXYWH,x,y,w,h);
  385.     win.total.x:=x;
  386.     win.total.y:=y;
  387.     win.total.w:=w;
  388.     win.total.h:=h;
  389.     WindowGet(u,WorkXYWH,x,y,w,h);
  390.     win.work.x :=x;
  391.     win.work.y :=y;
  392.     win.work.w :=w;
  393.     win.work.h :=h;
  394.     windowlist[u]^:=win;
  395.   END(*IF*);
  396. END  setWindow;
  397.  
  398. PROCEDURE topWindow    (u: window );
  399. VAR win : windowtype;
  400.       i : INTEGER;
  401.  
  402. BEGIN
  403.   IF  windowlist[u] # NIL THEN
  404.     win:=windowlist[u]^;
  405.     WindowSet(u,Top,u,0,0,0);
  406.     win.opened:=TRUE;
  407.     win.ontop:=TRUE;
  408.     windowlist[u]^:=win;
  409.     FOR i:= 0 TO maxwindow DO
  410.        IF windowlist[i] # NIL THEN
  411.           win:=windowlist[i]^;
  412.           IF win.handle#u THEN
  413.              win.ontop:=FALSE;
  414.              windowlist[i]^:=win;
  415.           END(*IF*);
  416.        END(*IF*);
  417.     END(*FOR*);
  418.   END(*IF*);
  419. END topWindow;
  420.  
  421. PROCEDURE MouseOn;
  422. BEGIN
  423.    GrafMouse(257,NIL)
  424. END  MouseOn;
  425.  
  426. PROCEDURE MouseOff;
  427. BEGIN
  428.    GrafMouse(256,NIL)
  429. END  MouseOff;
  430.  
  431.   (* Vor Ausgaben auf den Bildschirm muss die Maus ausgeschaltet werden,
  432.      da sonst das Maussymbol überschrieben wird und bei der nächsten
  433.      Bewegung der Maus der alte, zuvor von der Maus verdeckte Bildschirm-
  434.      inhalt wieder restauriert wird. Alle Prozeduren in diesem Modul, die
  435.      den Bildschirm verändern, schalten die Maus während der Ausgabe aus.
  436.      Während des Aufrufs der vom Benutzer bereitgestellten Redraw-Prozedur
  437.      beim Abarbeiten der Rechteckliste in "DoRedraw" wird die Maus eben-
  438.      falls ausgeschaltet, ruft der Benutzer dagegen selbst seine Redraw-
  439.      Prozedur auf oder benutzt er die weiter unten beschriebenen Textaus-
  440.      gabeprozeduren, muss er sich selbst um die Maus kümmern.
  441.  
  442.      Achtung:  Ein- und Ausschalten der Maus wird vom Betriebssystem
  443.                mitgezählt. Wird die Maus mehrmals ausgeschaltet, muß
  444.                sie genausooft wieder eingeschaltet werden, damit sie
  445.                sichtbar wird. Wird die Maus zu oft eingeschaltet, dann
  446.                entstehen beim Bewegen von Fenstern und Schiebern Schmutz-
  447.                effekte.
  448.   *)
  449.  
  450. PROCEDURE High(a:ADDRESS):INTEGER;
  451. VAR r : RECORD CASE : BOOLEAN OF
  452.                  TRUE   : w: ADDRESS;
  453.                  |FALSE : h,l :INTEGER;
  454.                  END(*CASE*);
  455.          END(*RECORD*);
  456. BEGIN
  457.    r.w:=a;
  458.    RETURN r.h
  459. END High;
  460.  
  461. PROCEDURE Low(a:ADDRESS):INTEGER;
  462. VAR r:RECORD CASE : BOOLEAN OF
  463.                 TRUE  : w   : ADDRESS;
  464.                |FALSE : h,l : INTEGER;
  465.              END(*CASE*);
  466.       END(*RECORD*);
  467. BEGIN
  468.    r.w:=a;
  469.    RETURN r.l
  470. END Low;
  471.  
  472.  
  473. PROCEDURE SetInfo      (u: window ; s: ARRAY OF CHAR);
  474. VAR win :windowtype;
  475.       t :wstring;
  476.       i :INTEGER;
  477. BEGIN
  478.    IF HIGH(s)>78 THEN
  479.       FOR i:= 0 TO 78 DO
  480.             t[i]:=s[i]
  481.       END(*FOR*);
  482.       t[79]:=0C
  483.    ELSE
  484.       FOR i:= 0 TO HIGH(s) DO
  485.            t[i]:=s[i]
  486.       END(*FOR*);
  487.       t[HIGH(s)+1]:=0C
  488.    END(*IF*);
  489.    IF  windowlist[u] # NIL THEN
  490.       win:=windowlist[u]^;
  491.       win.info:=t;
  492.       windowlist[u]^:=win;
  493.       WindowSet(u,WindowInfo,High(ADR(windowlist[u]^.info)),
  494.                              Low(ADR(windowlist[u]^.info)),0,0);
  495.   END(*IF*);
  496. END  SetInfo;
  497.  
  498.   (* Schreibt einen Text in die Info-Zeile des Fensters *)
  499.  
  500.  
  501. PROCEDURE SetTitle     (u: window ; s: ARRAY OF CHAR);
  502. VAR win :windowtype;
  503.     t   :  wstring;
  504.     i   :INTEGER;
  505. BEGIN
  506.    IF HIGH(s)>78 THEN
  507.       FOR i:= 0 TO 78 DO
  508.             t[i]:=s[i]
  509.       END(*FOR*);
  510.       t[79]:=0C
  511.    ELSE
  512.       FOR i:= 0 TO HIGH(s) DO
  513.            t[i]:=s[i]
  514.       END(*FOR*);
  515.       t[HIGH(s)+1]:=0C
  516.    END(*IF*);
  517.    IF  windowlist[u] # NIL THEN
  518.       win:=windowlist[u]^;
  519.       win.title:=t;
  520.       windowlist[u]^:=win;
  521.       WindowSet(u,WindowName,High(ADR(windowlist[u]^.title)),
  522.                              Low(ADR(windowlist[u]^.title)),0,0);
  523.   END(*IF*);
  524. END  SetTitle;
  525.  
  526.   (* Schreibt einen Text in die Titel-Zeile des Fensters. Der Text
  527.      bleibt beim Schliessen erhalten und wird beim Öffnen wieder
  528.      angezeigt
  529.    *)
  530.  
  531. PROCEDURE SetHorSlider (u: window ; wpos, wsize, total: INTEGER);
  532. VAR win :windowtype;
  533.     SliderSize,SliderPos :INTEGER;
  534. BEGIN
  535.   IF  windowlist[u] # NIL THEN
  536.     win:=windowlist[u]^;
  537.       MouseOff;
  538.       SliderSize:=wsize*1000 DIV  total;
  539.       IF total <= wsize THEN
  540.          SliderPos := 0;
  541.       ELSE
  542.          SliderPos:=wpos*1000 DIV total
  543.       END(*IF*);
  544.       WindowSet(u,WindowHorizSlide,SliderPos,0,0,0);
  545.       WindowSet(u,HorizSliderSize,SliderSize,0,0,0);
  546.       MouseOn;
  547.       win.row:=wpos;win.maxrow :=total;
  548.       windowlist[u]^:=win;
  549.   END(*IF*);
  550. END  SetHorSlider;
  551.  
  552.   (* siehe "SetVertSlider", setzt den horizontalen Schieber entsprechend
  553.      der horizontalen Position des Fensters im Gesamtdokument.
  554.   *)
  555.  
  556. PROCEDURE SetVertSlider (u: window ; wpos, wsize, total: INTEGER);
  557. VAR win :windowtype;
  558.     SliderSize,SliderPos :INTEGER;
  559. BEGIN
  560.   IF  windowlist[u] # NIL THEN
  561.       win:=windowlist[u]^;
  562.       MouseOff;
  563.       SliderSize:=wsize*1000 DIV  total;
  564.       IF total <= wsize THEN
  565.          SliderPos := 0;
  566.       ELSE
  567.          SliderPos:=wpos*1000 DIV total
  568.       END(*IF*);
  569.       WindowSet(u,WindowHorizSlide,SliderPos,0,0,0);
  570.       WindowSet(u,HorizSliderSize,SliderSize,0,0,0);
  571.       MouseOn;
  572.       win.col:=wpos;win.maxcol :=total;
  573.       windowlist[u]^:=win;
  574.   END(*IF*);
  575. END  SetVertSlider;
  576.  
  577.   (* Berechnet die korrekte Position und -grösse des vertikalen
  578.      Schiebers aus den Parametern, die die vertikale Position des
  579.      Fensters im Gesamtdokument beschreiben, und setzt den Schieber.
  580.      Die Schieber müssen, falls vorhanden, nach jeder Veränderung
  581.      der Fenstergrösse oder des Fensterinhalts neu gesetzt werden.
  582.  
  583.      Bedeutung der Parameter:
  584.  
  585.      wpos:   Anfangsposition des Fensters im Gesamtdokument
  586.      wsize:  Grösse des im Fenster dargestellten Teils des Gesamtdokuments
  587.      total:  Grösse des Gesamtdokuments
  588.   *)
  589.  
  590.  
  591.  
  592. PROCEDURE copyrect (u: window ; source, dest: rectangle);
  593. VAR win                       : windowtype;
  594.     XYWH                      : BigPxyArrayType;
  595.     Screen1MFDB,Screen2MFDB   : MFDBType;
  596.     x,y,w,h                   : INTEGER;
  597.  
  598. BEGIN
  599.   IF  windowlist[u] # NIL THEN
  600.     win:=windowlist[u]^;
  601.     IF win.opened THEN
  602.        MouseOff;
  603.        WindowGet(u,WorkXYWH,x,y,w,h);
  604.        source.x:=source.x+x;source.y:=source.y+y;
  605.        dest.x:=dest.x+x;dest.y:=dest.y+y;
  606.        Screen1MFDB.pointer:=0D;
  607.        Screen1MFDB.width:=source.w;
  608.        Screen1MFDB.height:=source.h;
  609.        Screen1MFDB.format:=1;
  610.        Screen1MFDB.rsrvd1:=0; Screen1MFDB.rsrvd2:=0;
  611.        XYWH[0]:=source.x; XYWH[1]:=source.y; XYWH[2]:=source.w+source.x; XYWH[3]:=source.h+source.y;
  612.        XYWH[4]:=dest.x;XYWH[5]:=dest.y; XYWH[6]:=dest.w+dest.x;XYWH[7]:=dest.h+dest.y;
  613.        Screen2MFDB.pointer:=0D;
  614.        Screen2MFDB.width:=dest.w;
  615.        Screen2MFDB.height:=dest.h;
  616.        Screen2MFDB.format:=1;
  617.        Screen2MFDB.rsrvd1:=0; Screen2MFDB.rsrvd2:=0;
  618.        CopyRasterOpaque(handle,3,XYWH,ADR(Screen1MFDB),ADR(Screen2MFDB));
  619.        MouseOn;
  620.     END(*IF*);
  621.   END(*IF*);
  622. END  copyrect;
  623.  
  624.   (* Kopiert innerhalb eines Fensters den Rechteckbereich "source" in
  625.      den Rechteckbereich "dest" (Koordinaten relativ zum Fensterursprung
  626.      links oben). Der freiwerdende Bereich von "source" muss bei Bedarf
  627.      gelöscht werden. Mit dieser Prozedur lassen sich Scroll-,
  628.      Insert- und Deletefunktionen in Textfenstern realisieren *)
  629.  
  630.  
  631. PROCEDURE scrollup (u: window );
  632. VAR win             : windowtype;
  633.     r1,r2,r3        : rectangle;
  634. BEGIN
  635.   IF  windowlist[u] # NIL THEN
  636.     win:=windowlist[u]^;
  637.     IF win.opened THEN
  638.        r1:=win.work; r2:=win.work;
  639.        r1.x:=win.scrollX; r1.y:=win.scrollY;
  640.        r1.w:=r1.w-win.scrollX; r1.h:=r1.h-win.scrollY;
  641.        r2.x:=0;r2.y:=0;
  642.        r2.w:=r2.w-win.scrollX; r2.h:=r2.h-win.scrollY;
  643.        r3.x:=win.work.w-win.scrollX; r3.y:=win.work.w-win.scrollY;
  644.        r3.w:=win.scrollY; r3.h:=win.scrollY;
  645.        copyrect(u,r1,r2);
  646.        clearrect(u,r3);
  647.        win.row:=win.row+1;
  648.        windowlist[u]^:=win;
  649.     END(*IF*);
  650.   END(*IF*);
  651. END  scrollup;
  652.  
  653.   (* Schiebt den Inhalt eines Textfensters eine Zeile nach oben, die
  654.      oberste Zeile verschwindet, die unterste wird gelöscht. "row"
  655.      wird auf "maxrow", "col" auf 0 gesetzt *)
  656.  
  657.  
  658. PROCEDURE scrolldown (u: window );
  659. VAR win             : windowtype;
  660.     r1,r2,r3        : rectangle;
  661. BEGIN
  662.   IF  windowlist[u] # NIL THEN
  663.     win:=windowlist[u]^;
  664.     IF win.opened THEN
  665.        r1:=win.work; r2:=win.work;
  666.        r1.x:=win.scrollX; r1.y:=win.scrollY;
  667.        r1.w:=r1.w-win.scrollX; r1.h:=r1.h-win.scrollY;
  668.        r2.x:=0;r2.y:=0;
  669.        r2.w:=r2.w-win.scrollX; r2.h:=r2.h-win.scrollY;
  670.        r3.x:=0;r3.y:=0;
  671.        r3.w:=win.scrollX; r3.h:=win.scrollY;
  672.        copyrect(u,r2,r1);
  673.        clearrect(u,r3);
  674.        IF win.row >0 THEN
  675.           win.row:=win.row-1
  676.        ELSE
  677.           win.row:=0;
  678.        END(*IF*);
  679.        windowlist[u]^:=win;
  680.     END(*IF*);
  681.   END(*IF*);
  682. END  scrolldown;
  683.  
  684.   (* Schiebt den Inhalt eines Textfenster eine Zeile nach unten, die
  685.      unterste Zeile verschwindet, die oberste wird gelöscht. "row"
  686.      und "col" werden auf 0 gesetzt *)
  687.  
  688.  
  689. PROCEDURE DrawCursor (u:window ; row, col: INTEGER);
  690. VAR win                       : windowtype;
  691.     XYWH                      : BigPxyArrayType;
  692.     ScreenMFDB                : MFDBType;
  693.     x,y,w,h                   : INTEGER;
  694.  
  695. BEGIN
  696.   IF  windowlist[u] # NIL THEN
  697.     win:=windowlist[u]^;
  698.     IF win.opened THEN
  699.        MouseOff;
  700.        WindowGet(u,WorkXYWH,x,y,w,h);
  701.        ScreenMFDB.pointer:=0D;
  702.        ScreenMFDB.width:=WC;
  703.        ScreenMFDB.height:=HC;
  704.        ScreenMFDB.format:=1;
  705.        ScreenMFDB.rsrvd1:=0; ScreenMFDB.rsrvd2:=0;
  706.        XYWH[0]:=x+row*WC; XYWH[1]:=y+row*HC; XYWH[2]:=XYWH[0]+HC; XYWH[3]:=XYWH[1]+WC;
  707.        XYWH[4]:=XYWH[0]; XYWH[5]:=XYWH[1]; XYWH[6]:=XYWH[2]; XYWH[7]:=XYWH[3];
  708.        CopyRasterOpaque(handle,12,XYWH,ADR(ScreenMFDB),ADR(ScreenMFDB));
  709.        MouseOn;
  710.     END(*IF*);
  711.   END(*IF*);
  712. END  DrawCursor;
  713.  
  714.   (* Zeichnet ein Rechteck in der Grösse eines Zeichenfeldes an die
  715.      angegebene Stelle innerhalb des Fensters. Da alle Pixel inver-
  716.      tiert werden, nimmt ein zweiter Aufruf mit denselben Parametern
  717.      den Cursor wieder weg. *)
  718.  
  719.  
  720. PROCEDURE WriteStr (u: window ; row, col: INTEGER; s: ARRAY OF CHAR);
  721. VAR win    : windowtype;
  722.     i,x,y,w,h: INTEGER;
  723.     Attributes : TextAttrArrayType;
  724. BEGIN
  725.   IF  windowlist[u] # NIL THEN
  726.     win:=windowlist[u]^;
  727.     IF win.opened THEN
  728.        MouseOff;
  729.        WindowGet(u,WorkXYWH,x,y,w,h);
  730.        x:=x+row*WC;
  731.        y:=y+col*HC;
  732.        InquireTextAttributes(handle,Attributes);
  733.        i:=SetGraphicTextColour(handle,win.textcolour);
  734.        i:=SetGraphicTextEffects(handle,VAL(INTEGER,win.texteffects));
  735.        GraphicText(handle,x,y,s);
  736.        i:=SetGraphicTextColour(handle,Attributes[1]);
  737.        i:=SetGraphicTextEffects(handle,0);
  738.        MouseOn;
  739.     END(*IF*);
  740.   END(*IF*);
  741. END  WriteStr;
  742.  
  743.   (* Gibt einen String ab der durch "row" (Zeile) und "col" (Spalte)
  744.      angegebenen Stelle aus. Zeile und Spalte beziehen sich auf den
  745.      Arbeitsbereich des Fensters. Das Zeichen in der linken oberen
  746.      Ecke hat die Koordinaten (0,0).  *)
  747.  
  748.  
  749. PROCEDURE WriteTextBlock (u: window ; row, col: INTEGER;
  750.                             adr: ADDRESS; count: INTEGER);
  751.  
  752.   (* Wie "WriteStr", nur wird der auszugebende String durch die Adresse
  753.      des ersten Zeichens und die Länge angegeben
  754.   *)
  755. END  WriteTextBlock;
  756.  
  757. PROCEDURE WriteTextBuffer (u: window ; adr: ADDRESS;
  758.                              count, offset: INTEGER);
  759.  
  760.   (* Gibt den ab der Adresse "adr" liegenden Text ins Fenster "u" ab
  761.      der Position (0,0) aus, bis entweder 0C im Text auftritt, "count"
  762.      erreicht wird oder das Fenster voll ist. Als Zeilenende wird lf
  763.      erkannt, cr wird ignoriert. Falls "offset" > 0, werden die ersten
  764.      "offset" Zeichen in jeder Zeile übersprungen, so dass sich hori-
  765.      zontale Fensterverschiebungen realisieren lassen. Diese Prozedur
  766.      eignet sich gut für das Redrawing von Textfensterpuffern.
  767.   *)
  768. END  WriteTextBuffer;
  769.  
  770.  
  771. PROCEDURE RectToPxy (VAR rect: rectangle; VAR pxy: PxyArrayType);
  772.  
  773. BEGIN
  774.    pxy[0]:=rect.x;
  775.    pxy[1]:=rect.y;
  776.    pxy[2]:=rect.x+rect.w;
  777.    pxy[3]:=rect.y+rect.h;
  778. END  RectToPxy;
  779.  
  780. PROCEDURE Intersect(r1:rectangle;VAR r2 :rectangle):BOOLEAN;
  781. VAR r : rectangle;
  782.  
  783.   PROCEDURE Min(a,b:INTEGER ):INTEGER;
  784.   BEGIN
  785.       IF a<b THEN RETURN a ELSE RETURN b END(*IF*);
  786.   END Min;
  787.  
  788.   PROCEDURE Max(a,b:INTEGER ):INTEGER;
  789.   BEGIN
  790.      IF a>b THEN RETURN a ELSE RETURN b END(*IF*);
  791.   END Max;
  792.  
  793. BEGIN
  794.    r.w:=Min(r1.x+r1.w,r2.x+r2.w); r.h:=Min(r1.y+r1.h,r2.y+r2.h);
  795.    r.x:=Max(r1.x,r2.x);r.y:=Max(r1.y,r2.y);
  796.    r2:=r; r2.w:=r.w-r.x; r2.h:=r.h-r.y;
  797.    RETURN ((r.w>r.x) AND (r.h>r.y))
  798. END Intersect;
  799.  
  800. PROCEDURE DoRedraw (u: window ; x, y, w, h: INTEGER; clip: BOOLEAN);
  801. VAR r,r1 : rectangle;
  802.     pxy  :PxyArrayType;
  803.     win : windowtype;
  804. BEGIN
  805.   IF  windowlist[u] # NIL THEN
  806.     win:=windowlist[u]^;
  807.  
  808.    r1.x:=x;r1.y:=y;r1.h:=h;r1.w:=w;
  809.    MouseOff;
  810.    WindowUpdate(BeginUpdate);
  811.    WindowGet(u,FirstXYWH,r.x,r.y,r.w,r.h);
  812.    WHILE (r.w>0) AND (r.h>0) DO
  813.      IF Intersect(r1,r) THEN
  814.        r.w:=r.w-1; r.h:=r.h-1;
  815.        RectToPxy(r,pxy);
  816.        IF clip THEN
  817.           SetClipping(handle,1,pxy);
  818.        END(*IF*);
  819.        win.redrawproc(u,r);
  820.      END(*IF*);
  821.     WindowGet(u,NextXYWH,r.x,r.y,r.w,r.h);
  822.    END(*WHILE*);
  823.    pxy[0]:=0; pxy[1]:=0; pxy[2]:=0; pxy[3]:=0;
  824.    SetClipping(handle,0,pxy);
  825.    WindowUpdate(EndUpdate);
  826.    MouseOn;
  827.  END(*IF*);
  828. END  DoRedraw;
  829.  
  830.   (* Holt sich von AES die Rechteckliste des Fensters w, schneidet die
  831.      erhaltenen Rechtecke mit dem Desktop und der als Parameter über-
  832.      gebenen Fläche und führt dann die erforderliche Anzahl von Auf-
  833.      rufen der Redraw-Prozedur, die beim Create-Aufruf angegeben wurde,
  834.      aus. "DoRedraw" ist somit die Aktion auf eine Redraw-Message. Mit
  835.      "clip" kann angegeben werden, ob "DoRedraw" selbst den Clipping-
  836.      Aufruf für VDI-Funktionen durchführen soll. In jedem Fall wird
  837.      während des Ablaufs von "DoRedraw" das Window-Update-Flag gesetzt
  838.      und die Maus ausgeschaltet.
  839.   *)
  840.  
  841. PROCEDURE wp (u:  window ): windowptr;
  842. BEGIN
  843.     RETURN windowlist[u];
  844. END wp;
  845.  
  846.  
  847.  
  848.  
  849.  
  850. BEGIN
  851.     FOR Nil2Max := -1 TO maxwindow DO
  852.           windowlist[Nil2Max]:= NIL
  853.     END(*FOR*);
  854.     handle:=GrafHandle(WC,HC,WB,HB);
  855.     growbox:=TRUE;
  856.     Snap:=FALSE;
  857.     AllignX :=1;
  858.     AllignY :=1;
  859. END EasyWindow.
  860.